package com.klikmee.sms.core.base.creators;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.klikmee.sms.core.base.Core;
import com.klikmee.sms.core.base.communicator.Communicator;
import com.klikmee.sms.core.base.dao.BulkMessageDAO;
import com.klikmee.sms.core.base.util.States;
import com.klikmee.sms.core.model.BulkMessage;
import com.klikmee.sms.core.model.Provider;
import com.klikmee.sms.core.model.ServiceChargingCategory;

/**
 * Implementation of {@link BulkMessageCreator} Creates bulk messages and
 * enqueues them by calling {@link Core#enqueueBulkMessage(BulkMessage)}
 * 
 * @author makcro
 * 
 */
public class SimpleBulkMessageCreatorImpl implements BulkMessageCreator {
	/**
	 * Reference to core
	 */
	protected Core			core;

	/**
	 * Dao instance used to save bulk messages
	 */
	protected BulkMessageDAO	bulkMessageDAO;
	/**
	 * Logger implementation
	 */
	private Logger			logger	= Logger.getLogger( SimpleBulkMessageCreatorImpl.class );

	public SimpleBulkMessageCreatorImpl() {

	}

	public void setCore(Core core) {
		this.core = core;
	}

	public void setBulkMessageDAO(BulkMessageDAO bulkMessageDAO) {
		this.bulkMessageDAO = bulkMessageDAO;
	}

	public void init() {

	}

	/**
	 * Resolves provider for bulk message and creates it.
	 * 
	 * @param text
	 *            text of message
	 * @param receiverIds
	 *            list of bulk receivers
	 * @param signatureText
	 *            signature of bulk message
	 * @param serviceChargingCategory
	 *            charging id for this bulk message
	 * 
	 * @return number of produces bulk messages
	 */
	public int createBulkMessage(String text, List<String> receiverIds, String signatureText, ServiceChargingCategory serviceChargingCategory) {

		int bulkCount = 0;

		for (String currentReceiverId : receiverIds) {

			// verify phone number
			Provider provider = resolveProvider( currentReceiverId );
			if (provider == null) {

				logger.warn( "Invalid phone number detected during sending bulk message [" + currentReceiverId + "]" );
			}

			// continue with sending bulk message
			BulkMessage bulkMessage = new BulkMessage();
			bulkMessage.setText( text );
			bulkMessage.setSenderId( signatureText );
			bulkMessage.setToNumber( currentReceiverId );
			bulkMessage.setProvider( provider );
			bulkMessage.setChargingCategory( serviceChargingCategory );

			bulkMessage.setState( States.BulkMessage.WAITING_TO_BE_SENT );

			// store bulk message into database
			bulkMessageDAO.create( bulkMessage );
			// submit message to bulk queue
			core.enqueueBulkMessage( bulkMessage );
			// increment count
			bulkCount++;

		}
		logger.debug( MessageFormat.format( "Created [{0}] bulk message(s)", bulkCount ) );
		// after processing all receiver IDs, return bulk count
		return bulkCount;
	}

	/**
	 * Resolves provider for this message. Iterates through list of registered
	 * communicators and tests if particular one can handle bulk message by
	 * calling {@link Communicator#canHandleBulkMessage(String)}
	 * 
	 * @param receiverId
	 *            receiver of bulk message
	 * @return privider instance if match successful, null other wise
	 */
	public Provider resolveProvider(String receiverId) {
		// this will be returned
		Provider provider = null;
		// iterate through all mapped communicators
		Map<String, Communicator> communicatorMap = core.getCommunicatorMap();
		Set<String> keys = communicatorMap.keySet();
		for (String string : keys) {
			Communicator communicator = communicatorMap.get( string );
			if (communicator.canHandleBulkMessage( receiverId )) {
				provider = communicator.getProvider();

				logger.debug( MessageFormat.format( "Resovled [{0}] provider for bulk message with receiver [{1}]", provider.getName(), receiverId ) );
				break;
			}
		}

		return provider;
	}
}
